home *** CD-ROM | disk | FTP | other *** search
- #include "xinternl.h"
- #include <conio.h>
- #include <mem.h>
-
- #include "xdefs.h"
-
- /*==================================================================
- XRECT.CPP contains the basic functions for rectangle fills and
- copies in mode X.
-
- These routines were written initially by Themie Gouthas and
- company and modified March 1995 by Victor B. Putz.
- ===================================================================*/
-
-
- extern unsigned char * pbVGABuffer;
- extern int ScrnLogicalByteWidth;
-
- unsigned char abLeftClipPlaneMask[] = {
- 0x0f,
- 0x0e,
- 0x0c,
- 0x08
- };
-
- unsigned char abRightClipPlaneMask[] = {
- 0x0f,
- 0x01,
- 0x03,
- 0x07
- };
-
- /*
- _OrderRectPoints() swaps two coordinates if necessary so that one is the top left
- and the other is the bottom right
- */
- inline void _SwapPoints(
- xScreenCoord_t * piLeft,
- xScreenCoord_t * piTop,
- xScreenCoord_t * piRight,
- xScreenCoord_t * piBottom
- )
- {
- xScreenCoord_t iTemp;
- if ( *piLeft > *piRight ) {
- iTemp = *piLeft;
- *piLeft = *piRight;
- *piRight = iTemp;
- }
- if ( *piTop > *piBottom ) {
- iTemp = *piTop;
- *piTop = *piBottom;
- *piBottom = iTemp;
- }
- }
-
-
- extern void _HorizontalLine(
- xPageHandle_t wOffset,
- xScreenCoord_t iLeftX,
- xScreenCoord_t iY,
- int iLength,
- xColor_t iColor
- );
-
-
- void x_rect_fill( /* draw a single colour filled rectangle */
- xScreenCoord_t wStartX,
- xScreenCoord_t wStartY,
- xScreenCoord_t wEndX,
- xScreenCoord_t wEndY,
- xPageHandle_t wPageBase,
- xColor_t wColor
- )
- {
- _SwapPoints( &wStartX, &wStartY, &wEndX, &wEndY );
- BYTE * pbBase;
- BYTE * pb;
- int iPortTemp;
- int i;
-
- int iXSize = ( wEndX - wStartX ) + 1;
- int iYSize = ( wEndY - wStartY ) + 1;
- //trivial case -- just draw a line
- if ( iYSize == 1 ) {
- _HorizontalLine( wPageBase, wStartX, wStartY, iXSize, wColor );
- }
-
- //set up our pointer to the top left of the rectangle
- pbBase = pbVGABuffer + wPageBase + ( ScrnLogicalByteWidth * wStartY ) + wStartX / 4;
-
- //Start on the left
- if ( iPortTemp = ( wStartX & 3 ) ) {
- outp( SC_INDEX, 0x02 );
- outp( SC_INDEX + 1, abLeftClipPlaneMask[ iPortTemp ] );
- pb = pbBase;
- i = iYSize;
- while ( i-- ) {
- *pb = ( BYTE )wColor;
- pb += ScrnLogicalByteWidth;
- }
- iXSize -= ( 4 - iPortTemp );
- pbBase++;
- }
- //now do the middle chunk
- if ( iPortTemp = ( iXSize / 4 ) ) {
- outpw( SC_INDEX, 0x0f02 );
- iXSize &= 3;
- pb = pbBase;
- i = iYSize;
- while ( i-- ) {
- memset( pb, wColor, iPortTemp );
- pb += ScrnLogicalByteWidth;
- }
- pbBase += iPortTemp;
- }
- //...and finally clean up the right edge
- if ( iXSize ) {
- outp( SC_INDEX, 0x02 );
- outp( SC_INDEX + 1, abRightClipPlaneMask[ iXSize ] );
- while ( iYSize-- ) {
- *pbBase = ( BYTE )wColor;
- pbBase += ScrnLogicalByteWidth;
- }
- }
- }
-
- extern xScreenCoord_t TopClip; /* Clipping rectangle */
- extern xScreenCoord_t BottomClip;
- extern xScreenCoord_t LeftClip;
- extern xScreenCoord_t RightClip;
-
-
- void x_rect_fill_clipped( /* draw a single colour filled */
- xScreenCoord_t StartX, /* and clipped rectangle */
- xScreenCoord_t StartY,
- xScreenCoord_t EndX,
- xScreenCoord_t EndY,
- xPageHandle_t PageBase,
- xColor_t color
- )
- {
- _SwapPoints( &StartX, &StartY, &EndX, &EndY );
- if ( StartX > RightClip ) {
- return;
- }
- if ( StartX < LeftClip ) {
- StartX = LeftClip;
- }
- if ( EndX < LeftClip ) {
- return;
- }
- if ( EndX > RightClip ) {
- EndX = RightClip;
- }
- if ( StartY > BottomClip ) {
- return;
- }
- if ( StartY < TopClip ) {
- StartY = TopClip;
- }
- if ( EndY < TopClip ) {
- return;
- }
- if ( EndY > BottomClip ) {
- EndY = BottomClip;
- }
-
- x_rect_fill( StartX, StartY, EndX, EndY, PageBase, color );
-
- }
-
- void x_cp_vid_rect( /* Copy rect region within VRAM */
- xScreenCoord_t SourceStartX,
- xScreenCoord_t SourceStartY,
- xScreenCoord_t SourceEndX,
- xScreenCoord_t SourceEndY,
- xScreenCoord_t DestStartX,
- xScreenCoord_t DestStartY,
- xPageHandle_t SourcePageBase,
- xPageHandle_t DestPageBase,
- int SourceBitmapWidth,
- int DestBitmapWidth
- )
- {
- _SwapPoints( &SourceStartX, &SourceStartY, &SourceEndX, &SourceEndY );
- //select bit mask to take all latches from the latches and none
- //from the CPU so we can write the latch contents directly to memory
- outpw( GC_INDEX, 0x0 + BIT_MASK );
- BYTE * pbSource = pbVGABuffer + ( SourceBitmapWidth / 4 ) * SourceStartY + ( SourceStartX / 4 ) + SourcePageBase;
- BYTE * pbDest = pbVGABuffer + ( DestBitmapWidth / 4 ) * DestStartY + ( DestStartX / 4 ) + DestPageBase;
- BYTE bLeftPlaneMask = abLeftClipPlaneMask[ SourceStartX & 3 ];
- BYTE bRightPlaneMask = abRightClipPlaneMask[ SourceEndX & 3 ];
- //now get the number of bytes to copy
- if ( SourceStartX > SourceEndX ) {
- return;
- }
- //this is really the bytes to copy minus one, since we know there must
- //be at least one byte ( if there isn't we just return )
- int iBytesToCopy = ( ( SourceEndX - 1 ) - ( SourceStartX & ( ~0x03 ) ) / 4 );
- if ( iBytesToCopy == 0 ) {
- bLeftPlaneMask &= bRightPlaneMask;
- }
- int iHeightToCopy = SourceEndY - SourceStartY;
- int iDestSkip = DestBitmapWidth / 4 - iBytesToCopy - 1;
- int iSourceSkip = SourceBitmapWidth / 4 - iBytesToCopy - 1;
- while ( iHeightToCopy-- ) {
- int i = iBytesToCopy;
- //do left edge
- outp( SC_INDEX + 1, bLeftPlaneMask );
- *pbDest++ = *pbSource++; //copied through latches...
- --i;
- //now since iBytesToCopy is the number of bytes to copy minus one,
- //if there was only the one byte we're now negative and if it's
- //zero we're ready for the right edge. If it's more than zero, we've
- //got the middle to do
- if ( i > 0 ) {
- //do the middle part
- outp( SC_INDEX + 1, 0x0f );
- while( i > 0 ) {
- *pbDest++ = *pbSource++;
- --i;
- }
- }
- //now check for the right edge;
- if ( i == 0 ) {
- outp( SC_INDEX + 1, bRightPlaneMask );
- *pbDest++ = *pbSource++;
- }
- pbDest += iDestSkip;
- pbSource += iSourceSkip;
- }
- //now restore the controller so that it reads all from the cpu and
- //not from the latches.
- outp( GC_INDEX + 1, 0xff );
- }
-
- /* Copy a rectangular region of a VGA screen, with x coordinates
- rounded to the nearest byte -- source and destination may overlap.
- SrcRight is rounded up, and the left edges are rounded down, to ensure
- that the pixels pointed to by the arguments are inside the rectangle.
-
- The width of the rectangle in bytes (width in pixels / 4)
- cannot exceed 255.
-
- By Matthew McKenzie, converted from assembler by V. Putz
-
- Note-- This seems to be a simplified version of x_cp_vid_rect with
- no left or right clipping ( just uses nibble boundaries ). It also
- includes a bit of sensing to determine where to start and how to
- increment counters. Beyond that the functions are essentially the same.
- */
-
- void x_shift_rect (
- xScreenCoord_t SrcLeft,
- xScreenCoord_t SrcTop,
- xScreenCoord_t SrcRight,
- xScreenCoord_t SrcBottom,
- xScreenCoord_t DestLeft,
- xScreenCoord_t DestTop,
- xPageHandle_t ScreenOffs
- )
- {
- _SwapPoints( &SrcLeft, &SrcTop, &SrcRight, &SrcBottom );
- //first get new "rounded" coordinates:
- int iSourceLeft = SrcLeft / 4;
- int iDestLeft = DestLeft / 4;
- int iSourceRight = ( SrcRight + 3 ) / 4;
- //now find out what copy type we're doing.
- enum copyType_t {
- fromTopLeft,
- fromBottomRight
- };
- copyType_t copyType = fromTopLeft;
- if ( DestTop == SrcTop ) {
- if ( SrcLeft == DestLeft ) {
- return;
- }
- if ( DestLeft < SrcLeft ) {
- copyType = fromTopLeft;
- }
- else {
- copyType = fromBottomRight;
- }
- }
- else if ( DestTop < SrcTop ) {
- copyType = fromTopLeft;
- }
- else {
- copyType = fromBottomRight;
- }
- //now find the skip and starting points
- int iWidthSkip = 0;
- int iXMotion = 0;
- BYTE * pbDest = NULL;
- BYTE * pbSource = NULL;
- int iBytesToCopy = iSourceRight - iSourceLeft;
- int iHeightToCopy = SrcBottom - SrcTop;
- switch ( copyType ) {
- case fromTopLeft:
- pbDest = pbVGABuffer + ScreenOffs + ( DestTop * ScrnLogicalByteWidth ) + iDestLeft;
- pbSource = pbVGABuffer + ScreenOffs + ( SrcTop * ScrnLogicalByteWidth ) + iSourceLeft;
- iWidthSkip = ScrnLogicalByteWidth - iBytesToCopy;
- iXMotion = 1;
- break;
- case fromBottomRight:
- pbDest = pbVGABuffer + ScreenOffs + ( ( DestTop + iHeightToCopy ) * ScrnLogicalByteWidth ) + iDestLeft + iBytesToCopy;
- pbSource = pbVGABuffer + ScreenOffs + ( SrcBottom * ScrnLogicalByteWidth ) + iSourceRight;
- iWidthSkip = -( ScrnLogicalByteWidth - iBytesToCopy );
- iXMotion = -1;
- break;
- }
- //okay! Now we just select the mask to copy all bits through the latches...
- outpw( SC_INDEX, 0x0f02 );
- outpw( GC_INDEX, BIT_MASK );
- //now copy the data!
- while ( iHeightToCopy-- ) {
- int i = iBytesToCopy;
- while( i-- ) {
- *pbDest = *pbSource;
- pbDest += iXMotion;
- pbSource += iXMotion;
- }
- pbDest += iWidthSkip;
- pbSource += iWidthSkip;
- }
- //now restore the controller so that it reads all from the cpu and
- //not from the latches.
- outp( GC_INDEX + 1, 0xff );
- }
-
-
- /*
- @func Fills a rectangular region with a given pattern. DOES NOT FUNCTION
- PROPERLY!
- */
- void x_rect_pattern(
- xScreenCoord_t StartX,
- xScreenCoord_t StartY,
- xScreenCoord_t EndX,
- xScreenCoord_t EndY,
- xPageHandle_t PageBase,
- BYTE * Pattern
- )
- {
- _SwapPoints( &StartX, &StartY, &EndX, &EndY );
- BYTE * pbDisplayPattern = pbVGABuffer + PATTERN_BUFFER;
- BYTE * pbDest = pbVGABuffer + PageBase + StartX / 4 + ( ScrnLogicalByteWidth * StartY );
-
- //download the pattern to screen memory
- BYTE * pbPatternCount = Pattern;
- outp( SC_INDEX, MAP_MASK );
- for ( int i = 4; i != 0; --i ) {
- outp( SC_INDEX + 1, 0x01 );
- *pbDisplayPattern = *pbPatternCount++;
- outp( SC_INDEX + 1, 0x02 );
- *pbDisplayPattern = *pbPatternCount++;
- outp( SC_INDEX + 1, 0x04 );
- *pbDisplayPattern = *pbPatternCount++;
- outp( SC_INDEX + 1, 0x08 );
- *pbDisplayPattern = *pbPatternCount++;
- ++pbDisplayPattern;
- }
- //select all bit transfer contents from the latches, not CPU
- outpw( GC_INDEX, BIT_MASK );
- int iTemp = *pbDisplayPattern;
- int iPortTemp = 0;
- x_rect_fill( StartX, StartY, EndX, EndY, PageBase, iTemp );
- return;
- /*
- outp( GC_INDEX + 1, 0xff );
-
-
- int iXSize = ( EndX - StartX ) + 1;
- int iYSize = ( EndY - StartY ) + 1;
-
- for ( i = iYSize; i != 0; --i ) {
- BYTE * pb = pbDest + ( ScrnLogicalByteWidth * ( iYSize - i - 1 ) );
- iTemp = pbDisplayPattern[ ( iYSize - i ) & 3 ];
- if ( iPortTemp = ( StartX & 3 ) ) {
- outp( SC_INDEX, 0x02 );
- outp( SC_INDEX + 1, abLeftClipPlaneMask[ iPortTemp ] );
- *pb++ = ( BYTE )iTemp;
- iXSize -= ( 4 - iPortTemp );
- pb++;
- }
- //now do the middle chunk
- if ( iPortTemp = ( iXSize / 4 ) ) {
- outpw( SC_INDEX, 0x0f02 );
- iXSize &= 3;
- memset( pb, iTemp, iPortTemp );
- pb += iPortTemp;
- }
- //...and finally clean up the right edge
- if ( iXSize ) {
- outp( SC_INDEX, 0x02 );
- outp( SC_INDEX + 1, abRightClipPlaneMask[ iXSize ] );
- *pb = ( BYTE )iTemp;
- }
- }
- */
- }
-
- void x_rect_pattern_clipped( /* draw a pattern filled clipped */
- xScreenCoord_t StartX, /* rectangle */
- xScreenCoord_t StartY,
- xScreenCoord_t EndX,
- xScreenCoord_t EndY,
- xPageHandle_t PageBase,
- BYTE * Pattern
- )
- {
- _SwapPoints( &StartX, &StartY, &EndX, &EndY );
- if ( StartX > RightClip ) {
- return;
- }
- if ( StartX < LeftClip ) {
- StartX = LeftClip;
- }
- if ( EndX < LeftClip ) {
- return;
- }
- if ( EndX > RightClip ) {
- EndX = RightClip;
- }
- if ( StartY > BottomClip ) {
- return;
- }
- if ( StartY < TopClip ) {
- StartY = TopClip;
- }
- if ( EndY < TopClip ) {
- return;
- }
- if ( EndY > BottomClip ) {
- EndY = BottomClip;
- }
-
- x_rect_pattern( StartX, StartY, EndX, EndY, PageBase, Pattern );
-
- }
-